import { Window_Base } from "@/windows/Window_Base.js";
import { Sprite_Cursor } from "@/sprites/Sprite_Cursor.js";
import { Sprite_Arrow } from "@/sprites/Sprite_Arrow.js";
import { TouchInput } from "@/core/TouchInput.js";
import { Input } from "@/core/Input.js";

export class Window_Selectable extends Window_Base {
    constructor(width, height,autoInit=true) {
        super(width, height,autoInit);
    }

    init(width,height){
        super.init(width,height);
        this.active = true;
        this.selectedIndex = -1;

        this.offsetX = 0;
        this.offsetY = 0;

        this.upArrow = null;
        this.downArrow = null;
        this.leftArrow = null;
        this.rightArrow = null;

        this.createCursor();

        this.refresh();
    }

    createCursor() {
        this.cursorSprite = new Sprite_Cursor(this.itemWidth(), this.itemHeight());
        this.selectAll=false;
        this.cursorSprite.move(this._padding, this._padding);

        this.cursorSprite.visible = false;
        this.addChild(this.cursorSprite);
    }

    activate(){
        super.activate();
        if(this.selectedIndex==-1){
            this.cursorSprite.hide();
        }else{
            this.cursorSprite.show();
            this.cursorSprite.activate();
        }
    }
    deactivate(){
        super.deactivate();
        this.cursorSprite.deactivate();
    }
    
    leave(){
        this.deactivate();
        this.cursorSprite.hide();
    }

    itemEnabled(index){return index<this.length();}

    onResponse(index) {}
    onResponseAll(){}
    onCancel(){}
    onSelectChanged(index,oldIndex){}

    column() { return 1; }
    viewColumn() { return 1; }
    row() { return 1; }
    viewRow() { return 1; }
    length() { return 1; }

    itemWidth() { return this.contentsWidth(); }
    itemHeight() { return this.lineHeight(); }
    containPoint(x, y) {
        return x > this._padding
            && y > this._padding
            && x < this.width - this._padding
            && y < this.height - this._padding;
    }

    viewContain(index){
        let column=this.column();
        let col=this.viewColumn();
        let row=this.viewRow();

        let x=index%column;
        let y=(index-x)/column;
        x-=this.offsetX;
        y-=this.offsetY;
        return x>=0&&y>=0&&x<col&&y<row;
    }

    releaseSelectAll(){
        this.selectAll=false;
        this.cursorSprite.setSize(this.itemWidth(), this.itemHeight());
        this.cursorSprite.deactivate();
    }

    setSelectAll(){
        this.selectAll=true;
        this.cursorSprite.setSize(this.contentsWidth(),this.contentsHeight());
        this.cursorSprite.move(this._padding,this._padding);
        this.cursorSprite.activate();
    }

    selectFromCoord(x, y) {
        let ctxX = x - this._padding;
        let ctxY = y - this._padding;
        let indexX = Math.floor(ctxX / this.itemWidth());
        let indexY = Math.floor(ctxY / this.itemHeight());
        let index = (this.offsetY + indexY) * this.column() + (this.offsetX + indexX);
        this.select(index);
    }

    select(index) {
        if(this.selectAll){
            if(this.cursorSprite.isActive()){
                this.onResponseAll();
            }else{
                this.cursorSprite.activate();
            }
        }else if (index!=-1&&this.selectedIndex == index) {
            this._selectSure(index);
        } else {
            this._selectCursorMove(index);
        }
    }

    _selectSure(index){
        if(this.itemEnabled(index)){
            this.onResponse(index);
        }else{
            //放音乐
        }
    }
    _selectCursorMove(index){
        this.cursorSprite.visible = true;
        if (index == -1) {
            this.cursorSprite.hide();
        } else {
            this.cursorSprite.activate();
            let column = this.column();
            this.cursorSprite.move(
                ((index % column) - this.offsetX) * this.itemWidth()+this._padding,
                (Math.floor(index / column) - this.offsetY) * this.itemHeight()+this._padding
            );
        }
        let oldIndex=this.selectedIndex;
        this.selectedIndex = index;
        this.onSelectChanged(index,oldIndex);
    }

    updateSelf() {
        if (this.active) {
            this.updateTouch();
            this.updateInput();
        }
    }

    updateTouch() {
        if (TouchInput.isTriggered()) {
            let { x, y } = this.toLocal({ x: TouchInput._x, y: TouchInput._y });
            if (this.containPoint(x, y)) {
                this.selectFromCoord(x, y);
            }
        }else if(TouchInput.isCancelled()){
            this.onCancel();
        }
    }

    updateInput() {
        if (Input.isTriggered('up')) {
            let column=this.column();
            let index = this.selectedIndex - column;
            if (index >= 0) {
                if(Math.floor(index/column)<this.offsetY){
                    --this.offsetY;
                    this.updateVerticleArrow();
                    this.drawItems();
                }
                this.select(index);
            }
        } else if (Input.isTriggered('down')) {
            let column=this.column();
            let index = this.selectedIndex + column;
            if (index < this.length()) {
                if(Math.floor(index/column)>=(this.offsetY+this.viewRow())){
                    ++this.offsetY;
                    this.updateVerticleArrow();
                    this.drawItems();
                }
                this.select(index);
            }
        } else if (Input.isTriggered('left')) {
            let index = this.selectedIndex - 1;
            let column = this.column();
            if (index > 0 && ((index % column) != column - 1)) {
                if((index%column)<this.offsetX){
                    --this.offsetX;
                    this.updateHorizontalArrow();
                    this.drawItems();
                }
                this.select(index);
            }
        } else if (Input.isTriggered('right')) {
            let index = this.selectedIndex + 1;
            let column = this.column();
            if (index < this.length() && (index % column) < column-1) {
                if((index%column)>=this.viewColumn()+this.offsetX){
                    ++this.offsetX;
                    this.updateHorizontalArrow();
                    this.drawItems();
                }
                this.select(index);
            }
        } else if (Input.isTriggered('ok')) {
            this.select(this.selectedIndex);
        }else if(Input.isTriggered('escape')){
            this.onCancel();
        }
    }

    updateVerticleArrow(){
        if (this.offsetY > 0) {
            if (!this.upArrow) {
                this.upArrow = new Sprite_Arrow(0);
                this.upArrow.anchor.set(0.5);
                this.upArrow.x = this.width / 2;
                this.upArrow.y = this._padding / 2;
                this.addChild(this.upArrow);
            } else {
                this.upArrow.visible = true;
            }
        } else if (this.upArrow?.visible) {
            this.upArrow.visible = false;
        }

        if (this.viewRow() + this.offsetY < this.row()) {
            if (!this.downArrow) {
                this.downArrow = new Sprite_Arrow(2);
                this.downArrow.anchor.set(0.5);
                this.downArrow.x = this.width / 2;
                this.downArrow.y = this.height- this._padding/ 2;
                this.addChild(this.downArrow);
            } else {
                this.downArrow.visible = true;
            }
        } else if (this.downArrow?.visible) {
            this.downArrow.visible = false;
        }
    }

    updateHorizontalArrow() {
        if (this.offsetX > 0) {
            if (!this.leftArrow) {
                this.leftArrow = new Sprite_Arrow(3);
                this.leftArrow.anchor.set(0.5);
                this.leftArrow.x = this._padding / 2;
                this.leftArrow.y = this.height / 2;
                this.addChild(this.leftArrow);
            } else {
                this.leftArrow.visible = true;
            }
        } else if (this.leftArrow?.visible) {
            this.leftArrow.visible = false;
        }

        if (this.viewColumn() + this.offsetX < this.column()) {
            if (!this.rightArrow) {
                this.rightArrow = new Sprite_Arrow(1);
                this.rightArrow.anchor.set(0.5);
                this.rightArrow.x = this.width - this._padding / 2;
                this.rightArrow.y = this.height / 2;
                this.addChild(this.rightArrow);
            } else {
                this.rightArrow.visible = true;
            }
        } else if (this.rightArrow?.visible) {
            this.rightArrow.visible = false;
        }
    }

    drawItem(index,x,y,width,height){}

    refreshItem(index){
        let column=this.column();
        let col=this.viewColumn();
        let row=this.viewRow();

        let x=index%column;
        let y=(index-x)/column;
        x-=this.offsetX;
        y-=this.offsetY;
        if(x>=0&&y>=0&&x<col&&y<row){
            let itemWidth=this.itemWidth();
            let itemHeight=this.itemHeight();
            let dx=x*itemWidth;
            let dy=y*itemHeight;
            this.contents.clearRect(dx,dy,itemWidth,itemHeight);
            this.drawItem(index,dx,dy,itemWidth,itemHeight);
        }
    }

    drawItems(){
        this.contents.clear();
        let column=this.column();
        let col=this.viewColumn();
        let row=this.viewRow();
        let itemWidth=this.itemWidth();
        let itemHeight=this.itemHeight();
        
        for(let i=0;i<col;++i){
            for(let j=0;j<row;++j){
                let index=(j+this.offsetY)*column+i+this.offsetX;
                if(index>=this.length())continue;
                this.drawItem(index,i*itemWidth,j*itemHeight,itemWidth,itemHeight);
            }
        }
    }

    refresh(){
        this.drawItems();
        this.updateVerticleArrow();
        this.updateHorizontalArrow();
    }
}